﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace Inovout.Web.Mvc
{
    public static class EncryptInputExtensions
    {
        public static readonly X509Certificate2 InputCertificate;
        static EncryptInputExtensions()
        {
            InputCertificate = new X509Certificate2(Path.Combine(HttpRuntime.AppDomainAppPath, "Configs/InputCertificate.pfx"), "a", X509KeyStorageFlags.MachineKeySet);

        }
        public static MvcHtmlString EncryptPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            //HttpCookie cookie = htmlHelper.ViewContext.RequestContext.HttpContext.Response.Cookies[AntiForgeryConfig.CookieName];
            //var httpContext = new HttpContextWrapper(HttpContext.Current);
            //httpContext.Response.Cookies.Set(new HttpCookie(AntiForgeryConfig.CookieName, "test") { HttpOnly = true });
            //return htmlHelper.PasswordFor(expression);
            string propertyName = ExpressionHelper.GetExpressionText(expression);
            return htmlHelper.PasswordFor(expression,
                new Dictionary<string, object> { { "data-encrypt", GenerateKey() } });
        }

        public static MvcHtmlString EncryptPasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
        {
            string propertyName = ExpressionHelper.GetExpressionText(expression);
            var attribute = new KeyValuePair<string, object>("data-encrypt", GenerateKey());
            htmlAttributes.Add(attribute);
            return MvcHtmlString.Create(htmlHelper.PasswordFor(expression, htmlAttributes) + GenerateEncryptHtml(propertyName));
        }

        private static string GenerateEncryptHtml(string propertyName)
        {
            //_encrypt_property
            string hidden = string.Format("<input type='hidden' name='_encrypt_property' value={0} />", propertyName);
            return hidden;
        }

        private static string GenerateKey()
        {
            RSACryptoServiceProvider publicKeyProvider = (RSACryptoServiceProvider)InputCertificate.PublicKey.Key;
            var publicKey = publicKeyProvider.ExportParameters(false);
            return BytesToHexString(publicKey.Modulus) + "|" + BytesToHexString(publicKey.Exponent);
        }
        private static string BytesToHexString(byte[] input)
        {
            StringBuilder hexString = new StringBuilder(64);

            for (int i = 0; i < input.Length; i++)
            {
                hexString.Append(String.Format("{0:X2}", input[i]));
            }
            return hexString.ToString();
        }


    }
}
